package com.xbongbong.paas.script.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasProcessTaskEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.model.PaasProcessNodeTaskModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.pojo.dto.DingtalkWorkrecordDTO;
import com.xbongbong.paas.service.CompanyConfigService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.companyconfig.pojo.CompanyConfigWorkrecordValuePojo;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workrecord.enums.WorkrecordResultEnum;
import com.xbongbong.pro.process.pojo.dto.WorkrecordUpdateTaskDTO;
import com.xbongbong.pro.script.pojo.dto.DingtalkNodeTaskDTO;
import com.xbongbong.pro.script.pojo.dto.DingtalkTemplateDTO;
import com.xbongbong.pro.service.dingtalk.WorkflowDingtalkService;
import com.xbongbong.process.ding.DingtalkWorkrecordService;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.sys.domain.dao.CompanyConfigDao;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.CompanyModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 创建钉钉待办模板 (访客计划接入钉钉待办)
 * @author xingxing.xiao
 * @date 2019/07/19 17:42
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/form/dingtalk/workrecord")
public class DingtalkTemplateController {
    private static final Logger LOG = LoggerFactory.getLogger(DingtalkTemplateController.class);

    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    @Resource
    private DingtalkWorkrecordService dingtalkWorkrecordService;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private CompanyConfigService companyConfigService;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private PaasProcessNodeTaskModel paasProcessNodeTaskModel;
    @Resource
    private CompanyConfigDao companyConfigDao;


    /**
     * 更新待办模板
     * @author xingxing.xiao
     */
    @RequestMapping(value = "/updateWorkrecordTemplate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String updateWorkrecordTemplate(@RequestBody @Valid DingtalkTemplateDTO dingtalkTemplateDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkTemplateDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        String corpid = dingtalkTemplateDTO.getCorpid();
        Boolean isAll = dingtalkTemplateDTO.getIsAll();
        JSONObject obj = new JSONObject();
        int count = 0;
        if (isAll) {
            // 全部
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("columns", new StringBuffer(" corpid, config_value "));
            param.put("configAlias", CompanyConfigEnum.DINGTALK_WORKRECORD.getAlias());
            param.put("del", DelEnum.NORMAL.getDel());
            List<CompanyConfigEntity> configList = companyConfigDao.findEntityList(param);
            for (CompanyConfigEntity entity : configList) {
                JSONObject jsonObject = JSONObject.parseObject(entity.getConfigValue());
                String dingtalkProcessCode = jsonObject.getString("dingtalkProcessCode");
                if (StringUtil.isNotEmpty(dingtalkProcessCode)) {
                    String reCode = companyConfigService.saveDingtalkProcessTemplate(dingtalkProcessCode, entity.getCorpid());
                    if (StringUtil.isNotEmpty(reCode)) {
                        count ++;
                    }
                }
            }
        } else {
            // 单个，当前公司
            CompanyConfigEntity companyConfigEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.DINGTALK_WORKRECORD.getAlias(), corpid);
            if (Objects.nonNull(companyConfigEntity)) {
                JSONObject jsonObject = JSONObject.parseObject(companyConfigEntity.getConfigValue());
                String dingtalkProcessCode = jsonObject.getString("dingtalkProcessCode");
                if (StringUtil.isNotEmpty(dingtalkProcessCode)) {
                    String reCode = companyConfigService.saveDingtalkProcessTemplate(dingtalkProcessCode, corpid);
                    if (StringUtil.isNotEmpty(reCode)) {
                        count ++;
                    }
                }
            }
        }

        obj.put("successCount", "成功更新模板：" + count);
        return obj.toJSONString();
    }

    /**
     * 删除模板
     *
     * @param dingtalkTemplateDTO
     * @author xingxing.xiao
     */
    @RequestMapping(value = "/delPorcessTemplate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String delPorcessTemplate(@RequestBody @Valid DingtalkTemplateDTO dingtalkTemplateDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkTemplateDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        JSONObject obj = new JSONObject();
        int successCount = 0;

        String corpid = dingtalkTemplateDTO.getCorpid();
        String processCode = dingtalkTemplateDTO.getProcessCode();

        boolean flag = dingtalkWorkrecordService.delPorcessTemplate(corpid, processCode);
        if (flag) {
            successCount++;
        }

        obj.put("successCount", "成功删除模板：" + successCount);
        return obj.toJSONString();
    }

    /**
     * 取消某个实例的所有待办任务
     * @param dingtalkNodeTaskDTO
     * @return
     * @throws
     * @author xingxing.xiao
     * @date 2019/10/10 21:37
     */
    @RequestMapping(value = "/cancelProcessInstanceTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cancelProcessInstanceTask(@RequestBody @Valid DingtalkNodeTaskDTO dingtalkNodeTaskDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkNodeTaskDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        JSONObject obj = new JSONObject();
        int successCount = 0;
        String corpid = dingtalkNodeTaskDTO.getCorpid();
        Integer processTaskId = dingtalkNodeTaskDTO.getProcessTaskId();
        PaasProcessTaskEntity taskEntity = paasProcessTaskModel.getByKey(processTaskId, corpid);
        if (taskEntity != null && Objects.nonNull(taskEntity.getDingtalkProcessInstanceId())) {
            List<String> activityIdList = paasProcessNodeTaskModel.getDingtalkProcessActivityId(corpid, processTaskId);
            for (String activityId : activityIdList) {
                WorkrecordUpdateTaskDTO workrecordUpdateTaskDTO = new WorkrecordUpdateTaskDTO();
                workrecordUpdateTaskDTO.setCorpid(corpid);
                workrecordUpdateTaskDTO.setDingtalkInstanceId(taskEntity.getDingtalkProcessInstanceId());
                workrecordUpdateTaskDTO.setDingtalkActivityId(activityId);
                boolean flag = dingtalkWorkrecordService.cancelWorkrecordTaskgroup(workrecordUpdateTaskDTO);
                if (flag) {
                    successCount++;
                }
            }
        }

        obj.put("successCount", "成功取消任务：" + successCount);
        return obj.toJSONString();
    }

    /**
     * 删除单个实例
     *
     * @param dingtalkNodeTaskDTO
     * @author xingxing.xiao
     */
    @RequestMapping(value = "/delSingleProcessInstanceId", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String delSingleProcessInstanceId(@RequestBody @Valid DingtalkNodeTaskDTO dingtalkNodeTaskDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkNodeTaskDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        JSONObject obj = new JSONObject();
        int successCount = 0;

        String corpid = dingtalkNodeTaskDTO.getCorpid();
        String processInstanceId = dingtalkNodeTaskDTO.getProcessInstanceId();
        boolean flag = dingtalkWorkrecordService.deleteWorkrecordInstance(corpid, processInstanceId);
        if (flag) {
            successCount++;
        }

        obj.put("successCount", "成功更新记录：" + successCount);
        return obj.toJSONString();
    }

    /**
     * 操作单个实例
     *
     * @param dingtalkNodeTaskDTO
     * @author xingxing.xiao
     */
    @RequestMapping(value = "/optSingleProcessInstanceId", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String optSingleProcessInstanceId(@RequestBody @Valid DingtalkNodeTaskDTO dingtalkNodeTaskDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkNodeTaskDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        JSONObject obj = new JSONObject();
        int successCount = 0;

        String corpid = dingtalkNodeTaskDTO.getCorpid();
        String processInstanceId = dingtalkNodeTaskDTO.getProcessInstanceId();
        String workrecordTaskStatus = dingtalkNodeTaskDTO.getWorkrecordTaskStatus();
        WorkrecordResultEnum workrecordResultEnum = WorkrecordResultEnum.getByAlias(workrecordTaskStatus);
        boolean flag = dingtalkWorkrecordService.updateWorkrecordInstance(corpid, processInstanceId, workrecordResultEnum);
        if (flag) {
            successCount++;
        }

        obj.put("successCount", "成功更新记录：" + successCount);
        return obj.toJSONString();
    }

    /**
     * 操作待办实例的单个任务(agree/refuse/CANCELED)
     *
     * @param dingtalkNodeTaskDTO
     * @return
     * @throws
     * @author xingxing.xiao
     * @date 2019/10/10 21:37
     */
    @RequestMapping(value = "/optSingleWorkrecordTask", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String optSingleWorkrecordTask(@RequestBody @Valid DingtalkNodeTaskDTO dingtalkNodeTaskDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkNodeTaskDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        String corpid = dingtalkNodeTaskDTO.getCorpid();
        String processInstanceId = dingtalkNodeTaskDTO.getProcessInstanceId();
        String workrecordTaskId = dingtalkNodeTaskDTO.getWorkrecordTaskId();
        String workrecordTaskStatus = dingtalkNodeTaskDTO.getWorkrecordTaskStatus();

        JSONObject obj = new JSONObject();
        int successCount = 0;
        WorkrecordUpdateTaskDTO workrecordUpdateTaskDTO = new WorkrecordUpdateTaskDTO();
        workrecordUpdateTaskDTO.setCorpid(corpid);
        workrecordUpdateTaskDTO.setDingtalkInstanceId(processInstanceId);
        workrecordUpdateTaskDTO.setDingtalkTaskId(workrecordTaskId);
        WorkrecordResultEnum workrecordResultEnum = WorkrecordResultEnum.getByAlias(workrecordTaskStatus);
        boolean flag = dingtalkWorkrecordService.updateSingleWorkrecordTask(workrecordUpdateTaskDTO, workrecordResultEnum);
        if (flag) {
            successCount++;
        }

        obj.put("successCount", "成功更新记录：" + successCount);
        return obj.toJSONString();
    }

    /**
     * 取消实例的单个流程节点任务
     *
     * @param dingtalkNodeTaskDTO
     * @author xingxing.xiao
     * @date 2019/09/16 14:30
     */
    @RequestMapping(value = "/cancelWorkrecordActivityId", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String cancelWorkrecordActivityId(@RequestBody @Valid DingtalkNodeTaskDTO dingtalkNodeTaskDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkNodeTaskDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        JSONObject obj = new JSONObject();
        int successCount = 0;
        String corpid = dingtalkNodeTaskDTO.getCorpid();
        String processInstanceId = dingtalkNodeTaskDTO.getProcessInstanceId();
        String workrecordActivityId = dingtalkNodeTaskDTO.getWorkrecordActivityId();

        WorkrecordUpdateTaskDTO workrecordUpdateTaskDTO = new WorkrecordUpdateTaskDTO();
        workrecordUpdateTaskDTO.setCorpid(corpid);
        workrecordUpdateTaskDTO.setDingtalkInstanceId(processInstanceId);
        workrecordUpdateTaskDTO.setDingtalkActivityId(workrecordActivityId);
        boolean flag = dingtalkWorkrecordService.cancelWorkrecordTaskgroup(workrecordUpdateTaskDTO);
        if (flag) {
            successCount++;
        }
        obj.put("successCount", "成功更新记录：" + successCount);
        return obj.toJSONString();
    }


    /**
     * 删除钉钉待办实例-针对公司
     *
     * @param dingtalkTemplateDTO
     * @author xingxing.xiao
     * @date 2019/09/16 14:30
     */
    @RequestMapping(value = "/deleteProcessInstance", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String deleteProcessInstance(@RequestBody @Valid DingtalkTemplateDTO dingtalkTemplateDTO) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkTemplateDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        JSONObject obj = new JSONObject();
        String corpid = dingtalkTemplateDTO.getCorpid();
        int successCount = 0;
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("columns", new StringBuffer(" corpid, dingtalk_process_instance_id "));
        if (!dingtalkTemplateDTO.getIsAll()) {
            // 查询单个公司
            param.put("corpid", corpid);
        }
        List<PaasProcessTaskEntity> processTaskEntityList = paasProcessTaskModel.getDingtalkProcessInstanceId(param);
        for (PaasProcessTaskEntity processTaskEntity : processTaskEntityList) {
            String corpId = processTaskEntity.getCorpid();
            String instanceId = processTaskEntity.getDingtalkProcessInstanceId();
            boolean flag = dingtalkWorkrecordService.deleteWorkrecordInstance(corpId, instanceId);
            if (flag) {
                successCount++;
            }
        }
        obj.put("successCount", "成功更新记录：" + successCount);

        return obj.toJSONString();
    }

    /**
     * 老公司默认开启钉钉待办
     * @param dingtalkWorkrecordDTO
     * @param br
     * @return
     * @throws
     * @author xingxing.xiao
     * @date 2019/09/25 20:40
     */
    @RequestMapping(value = "/createTemplate", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String createTemplate(@RequestBody @Valid DingtalkWorkrecordDTO dingtalkWorkrecordDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(dingtalkWorkrecordDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }

        JSONObject obj = new JSONObject();
        Integer total = 0;
        Integer successCount = 0;

        List<String> corpidList = dingtalkWorkrecordDTO.getCorpidList();
        if (Objects.nonNull(corpidList) && !corpidList.isEmpty()) {
            // 刷指定的公司(默认开启钉钉待办)
            total = corpidList.size();
        } else {
            // 刷所有没配置钉钉待办的公司(默认开启钉钉待办)
            corpidList = companyModel.getCorpidListNotInCompanyConfig(CompanyConfigEnum.DINGTALK_WORKRECORD.getAlias());
            total = corpidList == null ? 0 : corpidList.size();
        }

        successCount = insertWorkrecordConfig(corpidList);

        obj.put("totalCount", "应更新记录：" + total);
        obj.put("successCount", "成功更新记录：" + successCount);
        return obj.toJSONString();
    }

    /**
     * 插入配置表
     * @author xingxing.xiao
     * @date 2019/09/26 12:50
     */
    public Integer insertWorkrecordConfig(List<String> corpidList) {
        Integer successCount = 0;

        for (String corpid : corpidList) {
            String processCode = "";
            processCode = companyConfigService.saveDingtalkProcessTemplate(processCode, corpid);
            if (Objects.equals(processCode, "")) {
                continue;
            }
            CompanyConfigWorkrecordValuePojo configValueObj = new CompanyConfigWorkrecordValuePojo();
            configValueObj.setEnable(1);
            configValueObj.setBtnName("同步流程审批到钉钉待办事项");
            configValueObj.setTips("开启后，流程审批提醒将出现在钉钉待办事项中，方便你快速查看、操作。");
            configValueObj.setDingtalkProcessCode(processCode);
            String configValue = JSON.toJSONString(configValueObj);

            // 生成一条钉钉待办配置保存到 tb_company_config 表
            CompanyConfigEntity companyConfigEntity = new CompanyConfigEntity(corpid, CompanyConfigEnum.DINGTALK_WORKRECORD.getName(), CompanyConfigEnum.DINGTALK_WORKRECORD.getAlias(), configValue);

            try {
                companyConfigModel.insert(companyConfigEntity);
                successCount ++;
            } catch (Exception e) {
                LOG.error("插入配置表出错：", e);
            }
        }

        return successCount;
    }
}
